from django.http import HttpResponse
from PIL import Image, ImageDraw, ImageFilter, ImageFont, ImageChops
from openpolitics.models import Person
from promisecheck.models import Promise, Log, DateStats, Status
from django.db.models import Count
import math
from promisecheck.utils import rebuild_datestats

def _get_font(font_size, bold=False):
    if bold:
        font = ImageFont.truetype("/Library/Fonts/Arial Bold.ttf", font_size)
    else:
        font = ImageFont.truetype("/Library/Fonts/Arial.ttf", font_size)
    return font

def _draw_text(txt, font_size=38, color='white', shadow=True, bold=False):
    font = _get_font(font_size, bold)
    x,y = font.getsize(txt)
    im = Image.new("RGBA", (x,y))
    draw = ImageDraw.Draw(im)
    draw.text((0,0),txt, font = font, fill = color)
    if not shadow:
        return im
    (r,g,b,a) = im.split()
    shadow = Image.merge("RGBA", (a,a,a,a))
    shadow=shadow.filter(ImageFilter.BLUR)
    bck = im.size
    bck = Image.new("RGBA", bck, (0,0,0,255))
    bck = ImageChops.multiply(shadow, bck)
    bck = ImageChops.offset(bck, 0, 1)
    final = Image.composite(im, bck, a)
    return final

def _add_text(im, p, angle, csize):
    text = str(p) + "%"
    rad = math.radians(90-angle)
    dist = 0.6*(csize)
    txt = _draw_text(text, 32, bold=True)
    font = _get_font(32, bold=True)
    fx,fy = font.getsize(text)
    x = math.sin(rad)*dist
    y = math.cos(rad)*dist
    pos = (int(((csize+100)*2-fx)/2+x), int((csize*2-fy)/2+y))
    im.paste(txt, pos, txt)

def _add_legend(im, draw, categories):
    w = int((im.size[1])/4)
    lh = 40
    rs = 25
    for j in range(0,2):
        for i in range(0,4):
            if (4*j)+i>=len(categories):
                break
            value = categories[(4*j)+i]
            text = value[0]
            draw.ellipse((w*i+20,im.size[1]-200+(j*lh),w*i+20+rs,im.size[1]-200+rs+(j*lh)), fill=value[1])
            txt = _draw_text(text, 32, color='black', shadow=False)
            im.paste(txt, (w*i+40+rs,im.size[1]-200-(10)+(j*lh)), txt)

def _draw_pie_chart(values, categories):
    csize = 350
    im = Image.new('RGBA',(csize*2+200, csize*2+200), "white")

    draw = ImageDraw.Draw(im)
    c = csize
    s = float(csize)*0.9
    start = -90
    n=0
    total = sum(values)
    
    if total == 0:
        draw.ellipse((int(c+100-s),int(c-s), int(c+100+s), int(c+s)), outline='black')
    else:
        for i in values:
            angle = float(i)/float(total)*360.0
            draw.pieslice((int(c+100-s),int(c-s), int(c+100+s), int(c+s)),
                          int(0+start), int(angle+start),
                          outline='black',
                          fill=categories[n][1])
            start += angle
            n+=1
        start = -90
        for i in values:
            if i == 0:
                continue
            angle = float(i)/float(total)*360.0
            _add_text(im, int(float(i)/float(total)*100), start+(angle/2), csize)
            start += angle
    _add_legend(im, draw, categories)
    del draw
    im= im.resize((csize, csize), Image.ANTIALIAS)
    return im

###############

def _get_max(values):
    mx = 0
    for i in values:
        if len(i):
            n=max(i)
            if n>mx:
                mx=n
    return mx

def _draw_scale(draw, im, size, cats, values):
    mx = _get_max(values)
    categories = cats
    font_size=22
    # v cats
    lines = (float(0*mx), float(mx*0.25), float(mx*0.5), float(mx*0.75), mx)
    top = mx
    for i in lines:
        pos = 20+(size[1]-1)-(float(i)/top)*(size[1]-1)
        draw.line((80, pos, size[0]-80, pos), width=1, fill='rgb(100,100,100)')

    tl = []
    font = _get_font(font_size, bold=False)
    for i in lines:
        txt = _draw_text(str(i), font_size=font_size, color='black', shadow=False, bold=False)
        x, y = font.getsize(str(i))
        tl.append((txt, x, i))

    sw = max(tl, key=lambda x:x[1])[1]
    if sw<25:
        sw+=15
    for txt in tl:
        pos = (size[1]-1)-(float(txt[2])/top)*(size[1]-1)
        im.paste(txt[0], (int(sw-txt[1]),int(pos+6)), txt[0])

    # h cats
    cats = categories
    i = (size[0]-160)/(len(cats)-1)
    n=0
    for j in cats:
        txt = _draw_text(j, font_size=font_size, color='black', shadow=False, bold=False)
        font = _get_font(font_size, bold=False)
        x, y = font.getsize(j)
        im.paste(txt, (i*n+(x/2), size[1]+35), txt)
        n+=1

def _draw_values(draw, im, size, values, categories):
    mx = _get_max(values)
    step = float(im.size[0]-160)/(len(values[0])-1)
    arcsize = 7
    top = mx
    m=0
    for j in values:
        vp = 10
        n=0
        for i in j:
            color = categories[m][1]
            pos = (size[1]-1)-(float(i)/top)*(size[1]-1)+20
            if n<len(j)-1:
                npos = (size[1]-1)-(float(j[n+1])/top)*(size[1]-1)+20
                draw.line((65+vp, pos, 65+vp+step, npos), fill=color, width=8)
            vp += step
            n+=1
        n = 0
        vp = 10
        for i in j:
            color = categories[m][1]
            pos = (size[1]-1)-(float(i)/top)*(size[1]-1)+20
            draw.ellipse((65+vp-arcsize, pos-arcsize, 65+vp+arcsize, pos+arcsize), fill="white", outline=color)
            for f in range(0,7):
                draw.ellipse((65+vp-arcsize-f, pos-arcsize-f, 65+vp+arcsize+f, pos+arcsize+f), outline=color)
            vp += step
            n+=1
        m+=1

def _add_line_legend(im, draw, categories):
    w = int((im.size[1]-200)/2)
    lh = 30
    rs = 12
    for j in range(0,2):
        for i in range(0,3):
            value = categories[(3*j)+i]
            text = value[0]
            draw.ellipse((w*i+100,im.size[1]-100+(j*lh),w*i+100+rs,im.size[1]-100+rs+(j*lh)), outline=value[1], fill='white')
            for f in range(0,6):
                draw.ellipse((w*i+100-f,im.size[1]-100+(j*lh)-f,w*i+100+rs+f,im.size[1]-100+rs+(j*lh)+f), outline=value[1])
            txt = _draw_text(text, 26, color='black', shadow=False)
            im.paste(txt, (w*i+120+rs,im.size[1]-100-8+(j*lh)), txt)

def _draw_line_chart(cats, values):
    size = (482, 231)
    im = Image.new('RGB',(size[0]*2, (size[1]+100)*2), "white")
    categories = (
        ('nie ruszone', 'rgb(65,122,179)'),
        ('aktywne', 'rgb(98,170,95)'),
        ('gotowe', 'rgb(234,174,74)'),
        ('porzucone', 'rgb(214,59,64)'),
        ('zlamane', 'rgb(154,86,154)'),
        ('kompromis', 'rgb(168,172,171)'),
        ('wstrzymane', 'rgb(111,122,10)'),
    )
    
    draw = ImageDraw.Draw(im)
    _draw_scale(draw, im, (size[0]*2, size[1]*2), cats, values)
    _draw_values(draw, im, (size[0]*2, size[1]*2), values, categories)
    _add_line_legend(im, draw, categories)
    del draw
    im= im.resize((size[0], size[1]+100), Image.ANTIALIAS)
    return im 

def pie_chart(request,
              template_name='promisecheck'):
    statuses = Status.objects.all().order_by('id')
    categories = (
        (statuses[0].name, 'rgb(65,122,179)'),
        (statuses[1].name, 'rgb(234,174,74)'),
        (statuses[2].name, 'rgb(98,170,95)'),
        (statuses[3].name, 'rgb(214,59,64)'),
        (statuses[4].name, 'rgb(154,86,154)'),
        (statuses[5].name, 'rgb(168,172,171)'),
        (statuses[6].name, 'rgb(111,72,71)'),
    )
    pid = request.GET.get('person',None)
    if pid:
        person = Person.objects.get(pk=pid)
    promises = person.promises.all()
    values = [0,0,0,0,0,0,0]
    for promise in promises:
        values[promise.status.id-1] += 1
    im = _draw_pie_chart(values, categories)
    response = HttpResponse(mimetype="image/png")
    im.save(response, 'PNG')
    return response

def line_chart(request,
               template_name='promisecheck'):
    pid = request.GET.get('person',None)
    if pid:
        person = Person.objects.get(pk=pid)
    promises = person.promises.all()
    rebuild_datestats(pid=person.id)
    cats = []
    values = [[],[],[],[],[],[],[]]
    dsl = DateStats.objects.all().order_by('date')
    for ds in dsl:
        day = ds.date.strftime("%Y.%m.%d")
        if not day in cats:
            cats.append(day)
        values[ds.status.pk-1].append(ds.value)

    im = _draw_line_chart(cats, values)
    response = HttpResponse(mimetype="image/png")
    im.save(response, 'PNG')
    return response
